package ack.service;

import com.rabbitmq.client.Channel;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.messaging.handler.annotation.Headers;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.Map;

@Service
public class AckListenerServiceImpl {
  /**
   * none：表示不做任何的签收确认（相当于⽆ack,等价于 Channel.basicConsume()的autoAck=true，只要消费端收到消息，就回复确认，至于消息是否正确被消费是不关心的），
   * 不管消费者是否正常消费消息， broker都认为消息已经被正常消费，并从broker中移除此消息。
   * 这样会导致消费端在处理消息的过程中如果产⽣异常，那么消息就会丢失。
   *
   * @param msg
   */
    @RabbitListener(queues = "ackqueue")
    public void receiveMsgNone(String msg) {
        System.out.println("接收到消息none--msg = " + msg);
        throw new RuntimeException("runtime ex");
    }

  /**
   *      * auto：表示⾃动确认，⾃动确认会根据消费端在处理消息的过程是否抛出异常来决定返回ack或者nack给broker。如
   *      * 果消费成功则返回ack， broker接收到ack后⾃动从队列中移除此消息。如果消费过程抛出了异常导则返回nack，此
   *      * 时broker会根据default-requeue-rejected的设置决定是否将消息重新放回队列中。
   *      *
   * @param msg
   */
 /*   @RabbitListener(queues = "ackqueue")
    public void receiveMsgAuto(String msg) {
        System.out.println("接收到消息auto--msg = " + msg);
        throw new RuntimeException("runtime ex");
    }*/

  /**
   * 手动应答
   * 由代码channel.basicAck确认应答
   * 由代码channel.basicNack或channel.basicReject拒绝应答
   *
   * @param message
   * @param headers
   * @param channel:导入的是com.rabbitmq.client.Channel
   * @throws IOException
   */
  /*@RabbitListener(queues = "ackqueue")
  public void receiveMessageManual(@Payload String message,
                                   @Header(AmqpHeaders.DELIVERY_TAG) Long deliveryTag,
                                   @Headers Map<String, Object> headers,
                                   Channel channel) throws IOException {
    //    Long deliveryTag = (Long) headers.get(AmqpHeaders.DELIVERY_TAG);
    try {
      System.out.println("接收消息： " + message);
      //从headers中获取⼀个唯⼀标识

      System.out.println("deliveryTag = " + deliveryTag);
      // throw new RuntimeException("re---");
      //确认签收
      //参数1：消息投递的唯⼀标识
      //参数2：是否⽀持批量签收（true表示批量确认， false表示单个确认）

      //不执行下面的代码,服务端会收不到应答,会一直等待客户端的应答,消息还没有重新入队,状态不是ready状态(15672管理界面可以看到,getMessage也收不到消息)
      //停止程序服务端就等价于确定收不到应答,消息状态就重新入队并且状态也变为ready状态,这样就可以收到消息了
      //    channel.basicAck(deliveryTag, false);

    } catch (Exception ex) {
      // 参数2：是否一次应答多个消息（批量应答，就是tag小于等于deliverTag的消息都应答）
      // 参数3：确定消息是否重新入队，true就是入队
      channel.basicNack(deliveryTag, false, false);

    }

  }*/
}
